package
{
	import Hxw3DEngine.asset.AssetManage;
	import Hxw3DEngine.asset.loader.AssetLoader;
	import Hxw3DEngine.asset.loader.AssetQueueLoader;
	import Hxw3DEngine.asset.parsers.ATFParser;
	import Hxw3DEngine.asset.parsers.BsonParser;
	import Hxw3DEngine.asset.parsers.MD2Parser;
	import Hxw3DEngine.asset.parsers.ObjParser;
	import Hxw3DEngine.asset.parsers.ParserEvent;
	import Hxw3DEngine.asset.parsers.bson.vo.MaterialTexture;
	import Hxw3DEngine.asset.parsers.bson.vo.MeshVO;
	import Hxw3DEngine.asset.parsers.bson.vo.Stream;
	import Hxw3DEngine.core.Resource.ResourceSkeleton;
	import Hxw3DEngine.core.Resource.animation.SkeletonAnimationClip;
	import Hxw3DEngine.core.Resource.animation.UVAnimationClip;
	import Hxw3DEngine.core.Resource.geometry.ResourceGeometry;
	import Hxw3DEngine.core.Resource.texture.ATFTexture;
	import Hxw3DEngine.core.Resource.texture.BitmapTexture;
	import Hxw3DEngine.core.component.Skeleton;
	import Hxw3DEngine.core.component.animation.SkeletonAnimation;
	import Hxw3DEngine.core.component.animation.SkeletonClipCacheSet;
	import Hxw3DEngine.core.component.animation.UVAnimation;
	import Hxw3DEngine.core.component.animation.VertexAnimation;
	import Hxw3DEngine.core.component.renderer.MeshRenderer;
	import Hxw3DEngine.core.component.renderer.SkinnedMeshRenderer;
	import Hxw3DEngine.core.component.sound.Sound3D;
	import Hxw3DEngine.core.controller.View3D;
	import Hxw3DEngine.core.display.Coordinate;
	import Hxw3DEngine.core.display.Cube3D;
	import Hxw3DEngine.core.display.GameObject;
	import Hxw3DEngine.core.display.Panel3D;
	import Hxw3DEngine.core.display.Rectangle3D;
	import Hxw3DEngine.core.display.SkyBox;
	import Hxw3DEngine.core.lights.DirectionalLight;
	import Hxw3DEngine.core.materials.TextureMaterial;
	import Hxw3DEngine.core.materials.shader.SkinnedShader;
	import Hxw3DEngine.core.materials.shader.filters.BillboardFilter;
	import Hxw3DEngine.core.materials.shader.filters.DirectionalLightFilter;
	import Hxw3DEngine.core.materials.shader.filters.FogFilter;
	import Hxw3DEngine.utils.Color;
	import Hxw3DEngine.utils.FPS;
	import Hxw3DEngine.utils.Stage3dUtils;
	
	import flash.display.Sprite;
	import flash.display3D.Context3DCompareMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Vector3D;
	
	
	[SWF(width="800",height="600",frameRate="60")]
	public class Demo
	{
		private var urlPrefix:String;
		private var sprite:Sprite;

		private var urlEnvPosX:String ="skybox/snow/px.jpg";
		private var urlEnvPosY:String ="skybox/snow/py.jpg";
		private var urlEnvPosZ:String ="skybox/snow/pz.jpg";
		private var urlEnvNegX:String ="skybox/snow/nx.jpg";
		private var urlEnvNegY:String ="skybox/snow/ny.jpg";
		private var urlEnvNegZ:String ="skybox/snow/nz.jpg";
		
		private var floorUrl:String = "floor/3.jpg";
		
		private var ObjDiffuseUrl:String = "obj/terrain/diffuse.jpg";
		
		private var ObjUrl:String = "obj/terrain/obj.obj";
		
		private var md2DiffuseUrl:String = "md2/hero/diffuse1.png";
		
		private var md2Url:String = "md2/hero/obj.md2";
		//测试光照
		private var testLightDiffuseUrl:String = "obj/head/diffuse.jpg"
			
		private var testLightNormalUrl:String = "obj/head/normals.jpg"
		
		private var testLightObjUrl:String = "obj/head/obj.obj";
		
		private var bgSoundUrl:String = "Sound/bg.mp3";
		
		private var bgSoundTest:String = "Sound/duan.mp3";
		
		private var UVanimationUrl:String = "texture/xulie_H_00002.png";
		
		private var UVanimationUrl1:String = "texture/xulie_45b.png";
		
		private var UVanimationUrl2:String = "texture/xulie_12.png"
		
		private var bsonSkeletonUrl:String = "bson/skeleton.bson";
		private var bsonSkinUrl:String = "bson/skin001.bson";
		private var bsonActionUrl:String = "bson/idle.bson";
		
		private var atfOldUrl:String = "texture/xulie_12.png.atf";
		private var atfNewUrl:String = "texture/xulie_12.atf";
		
		private var light:DirectionalLight = new DirectionalLight();
		
		private var view:View3D;
		
		// static initializer
		{
			SkeletonClipCacheSet.enable = true;
			SkeletonClipCacheSet.cache_skeletons(new <String>["skeleton.bson"]);
			SkeletonClipCacheSet.cache_animators(new <String>["idle"]);
		}
		
		public function Demo(_sprite:Sprite,_urlPrefix:String)
		{
			light.color = new Color(0xffffff);
			light.power = 100;
			light.transform.setPosition(0,50,-50);
			
			urlPrefix = _urlPrefix;
			sprite = _sprite;
			AssetLoader.url_prefix = urlPrefix + "/";

			//init engine
			view = new View3D();
			sprite.addChild(view);
			view.camera.setPosition(0,0,0);
			view.camera.lookAt(new Vector3D(0, 0, 0), new Vector3D(0, 10, -25), new Vector3D(0, 1, 0));
			
			//帧显示
			sprite.addChild(FPS.insdance);
			
			//给场景加个音效组件来播放声音
			var sound:Sound3D = new Sound3D();
			sound.url = bgSoundUrl;
			sound.isLoop = true;
			//sound.play();
			view.scene.addComponent(sound);
			
			
			//队列加载资源			
			var res:Array = [
				urlEnvPosX,
				urlEnvPosY,
				urlEnvPosZ,
				urlEnvNegX,
				urlEnvNegY,
				urlEnvNegZ,		
				
				testLightDiffuseUrl,
				testLightNormalUrl,
				testLightObjUrl,
			
				floorUrl,
				ObjDiffuseUrl,
				ObjUrl,
				md2DiffuseUrl,
				md2Url,
				UVanimationUrl,
				UVanimationUrl1,
				UVanimationUrl2,
				
				bsonSkeletonUrl,
				bsonSkinUrl,
				bsonActionUrl,
				
				atfOldUrl,
				atfNewUrl
			];
			var loder:AssetQueueLoader = new AssetQueueLoader(res,initThis);
			loder.startLoad();
			
		}
		
		//md2解析器
		private var md2parser:MD2Parser;
		//obj解析器
		private var parser:ObjParser;
		//light
		private var lightParser:ObjParser;
		
		private var skeletonParser:BsonParser;
		private var skinParser:BsonParser;
		private var actionParser:BsonParser;
		
		private var atfParserOld:ATFParser;
		private var atfParserNew:ATFParser;
		
		private function initThis():void {
			
			//一个天空盒
			var skybox:SkyBox = new SkyBox(
						Stage3dUtils.bitmapData(AssetManage.getAsset(urlEnvPosX)), 
						Stage3dUtils.bitmapData(AssetManage.getAsset(urlEnvNegX)),
						Stage3dUtils.bitmapData(AssetManage.getAsset(urlEnvPosY)), 
						Stage3dUtils.bitmapData(AssetManage.getAsset(urlEnvNegY)), 
						Stage3dUtils.bitmapData(AssetManage.getAsset(urlEnvPosZ)), 
						Stage3dUtils.bitmapData(AssetManage.getAsset(urlEnvNegZ))
						);
			view.scene.addChild(skybox);
			
			
			//一个地面
			var p:Panel3D = new Panel3D(new TextureMaterial(BitmapTexture.create(Stage3dUtils.bitmapData(AssetManage.getAsset(floorUrl)), true)),10,10,2);
			view.scene.addChild(p);
			
			view.scene.addChild(new Coordinate());
			
			//坐标系
			view.scene.addChild(new Coordinate());
			
			//立方体
			for (var i:int = 0; i < 5; i++ ) {
				for (var j:int = 0; j < 5; j++ ) {
					var c:Cube3D = new Cube3D(new Color(0xffffff*Math.random()));
					c.transform.setPosition( -5 * Math.random(), 5 * Math.random(), 5 * Math.random());
					MeshRenderer(c.getComponent(MeshRenderer)).material.twoSided = true;
					view.scene.addChild(c);
				}
			}
			
			//一个矩形
			
			var rectMat:TextureMaterial = new TextureMaterial(BitmapTexture.create(Stage3dUtils.bitmapData(AssetManage.getAsset(UVanimationUrl)), true));
			
			var rect:Rectangle3D = new Rectangle3D(rectMat,5, 5);
			rectMat.transparent = true;
			rectMat.depthWrite = false;
			rectMat.depthCompare = Context3DCompareMode.LESS_EQUAL;
			MeshRenderer(rect.getComponent(MeshRenderer)).material.shader.addFilter(new BillboardFilter());
			
			var uvani:UVAnimation = new UVAnimation(new UVAnimationClip("",4, 4));
			rect.addComponent(uvani);
			uvani.playAction();			
			
			view.scene.addChild(rect,1);
			rect.transform.setPosition(3, 2, 0);
			
			sprite.stage.addEventListener(MouseEvent.MOUSE_WHEEL,onWheel);
			sprite.stage.addEventListener(MouseEvent.MOUSE_DOWN,onDown);
			sprite.stage.addEventListener(MouseEvent.MOUSE_MOVE,onMove);
			sprite.stage.addEventListener(MouseEvent.MOUSE_UP,onUp);	
			sprite.addEventListener(Event.ENTER_FRAME,onEnter);
			
			parser= new ObjParser();
			parser.addEventListener(ParserEvent.PARSERCOMPLETE,onComplete);
			parser.startParser(AssetManage.getAsset(ObjUrl));
			
			md2parser = new MD2Parser();
			md2parser.addEventListener(ParserEvent.PARSERCOMPLETE,onMd2Complete);
			md2parser.startParser(AssetManage.getAsset(md2Url));
			
			skeletonParser = new BsonParser(bsonSkeletonUrl);

			skeletonParser.addEventListener(ParserEvent.PARSERCOMPLETE, onBsonComplate);
			skeletonParser.startParser(AssetManage.getAsset(bsonSkeletonUrl));

			skinParser = new BsonParser(bsonSkinUrl);
			skinParser.addEventListener(ParserEvent.PARSERCOMPLETE, onBsonComplate);

			skinParser.startParser(AssetManage.getAsset(bsonSkinUrl));

			actionParser = new BsonParser(bsonActionUrl);
			actionParser.addEventListener(ParserEvent.PARSERCOMPLETE, onBsonComplate);
			actionParser.startParser(AssetManage.getAsset(bsonActionUrl));
			
			/*atfParserOld = new ATFParser(atfOldUrl);
			atfParserOld.addEventListener(ParserEvent.PARSERCOMPLETE, onATFComplate);
			atfParserOld.startParser(AssetManage.getAsset(atfOldUrl));*/
			
			atfParserNew = new ATFParser(atfNewUrl);
			atfParserNew.addEventListener(ParserEvent.PARSERCOMPLETE, onATFComplate);
			atfParserNew.startParser(AssetManage.getAsset(atfNewUrl));
			
			lightParser = new ObjParser();
			lightParser.addEventListener(ParserEvent.PARSERCOMPLETE, onLightObject);
			lightParser.startParser(AssetManage.getAsset(testLightObjUrl));
			
		}
		
		private function onMd2Complete(e:Event):void {
			var obj:GameObject = new GameObject();
			var meshRender:MeshRenderer = new MeshRenderer();
			obj.addComponent(meshRender);

			meshRender.geometry = new ResourceGeometry();
			meshRender.geometry.createFormVectors(md2parser.numVertices,null,md2parser._indices,md2parser._finalUV);

			var bitmaptexture:BitmapTexture = BitmapTexture.create(Stage3dUtils.bitmapData(AssetManage.getAsset(md2DiffuseUrl)), true);
			var texturema:TextureMaterial = new TextureMaterial(bitmaptexture);
			meshRender.material = texturema;
			
			meshRender.material.shader.addFilter(new FogFilter(15,new Color(0x00ffaa)));
			
			//meshRender.material.shader.addFilter(new DirectionalLightFilter(light));
			
			obj.transform.setRotation(0, 90, 0);
			obj.transform.setScale(0.15, 0.15, 0.15);
			obj.transform.setPosition(8,3.5,0);
			
			//再设动画控制器
			var meshAni:VertexAnimation = new VertexAnimation(md2parser.vectexs, Stream.stream_positions);
			obj.addComponent(meshAni);
			meshAni.isLoop = true;
			meshAni.delay = 133.33333;
			meshAni.playAction("run");

			view.scene.addChild(obj);
		}
		
		private function onBsonComplate(e:Event):void {
			if (skeletonParser.isDone && skinParser.isDone && actionParser.isDone) {
				onBsonAllComplate();
			}
		}
		private function onBsonAllComplate():void {
			
			var obj:GameObject = new GameObject();
			
			var skeletonResource:ResourceSkeleton = new ResourceSkeleton();
			skeletonResource.createFromVO(skeletonParser.documentVO.skeleton);
			var skeleton:Skeleton = new Skeleton(skeletonResource);
			obj.addComponent(skeleton);
			
			for (var i:int = 0; i < skinParser.documentVO.meshes.length;i++ ) {
				var skinnedMeshRender:SkinnedMeshRenderer = new SkinnedMeshRenderer();
				obj.addComponent(skinnedMeshRender);

				skinnedMeshRender.geometry = new ResourceGeometry();
				skinnedMeshRender.geometry.createFromVO(skinParser.documentVO.meshes[i]);
				
				var materialIndex:uint = MeshVO(skinParser.documentVO.meshes[i]).material;
				var materialVO:MaterialTexture = MaterialTexture(skinParser.documentVO.materials[materialIndex]);
				var texture:uint = materialVO.diffuse_texture;
				var bitmaptexture:BitmapTexture = BitmapTexture.create(skinParser.bitmapData[texture], true);
				var shader:SkinnedShader = new SkinnedShader();
				shader.addFilter(new FogFilter(15,new Color(0x00ffaa)));
				shader.texture = bitmaptexture;
				var material:TextureMaterial = new TextureMaterial(bitmaptexture,shader);
				skinnedMeshRender.material = material;
				
			}
			
			var animationClip:SkeletonAnimationClip = new SkeletonAnimationClip("run", actionParser.documentVO.skeleton_anim);
			var animation:SkeletonAnimation = new SkeletonAnimation();
			animation.isLoop = true;
			animation.addClip(animationClip);
			obj.addComponent(animation);
			animation.playAction(animationClip.name);
			
			obj.transform.setScale(0.06, 0.06, 0.06);
			obj.transform.setPosition(-7,0,0);

			
			view.scene.addChild(obj);

		}
		
		private function onATFComplate(e:Event):void {
			var rectMat:TextureMaterial = new TextureMaterial(ATFTexture.create(ATFParser(e.target).atf));
			var rect:Rectangle3D = new Rectangle3D(rectMat,5,5);
			rectMat.transparent = true;
			rectMat.depthWrite = false;
			rectMat.depthCompare = Context3DCompareMode.LESS_EQUAL;
			
			MeshRenderer(rect.getComponent(MeshRenderer)).material.shader.addFilter(new BillboardFilter());
			
			var uvani:UVAnimation = new UVAnimation(new UVAnimationClip("",5, 3));
			rect.addComponent(uvani);
			uvani.playAction();		
			
			view.scene.addChild(rect,1);
			
			if (ATFParser(e.target).url == atfOldUrl) {
				rect.transform.setPosition(4,6,3);
			}else {
				rect.transform.setPosition(0,6,6);
			}
		}
		
		private function onComplete(e:Event):void {
			var obj:GameObject = new GameObject();
			var meshRender:MeshRenderer = new MeshRenderer();
			obj.addComponent(meshRender);
			meshRender.geometry = new ResourceGeometry();
			meshRender.geometry.createFormVectors(parser.numVertices,parser.vertexData,parser.indexData,parser.uvData,parser.normalData,parser.tangentData);
			meshRender.material = new TextureMaterial(BitmapTexture.create(Stage3dUtils.bitmapData(AssetManage.getAsset(ObjDiffuseUrl)), true))
			meshRender.material.shader.addFilter(new FogFilter(10,new Color(0xff0000)));
			obj.transform.setPosition(0, -2, 0);
			obj.transform.setScale(0.007,0.007,0.007);
			obj.transform.setRotation(0,180,0);
			view.scene.addChild(obj);
		}
		
		private function onLightObject(e:Event):void{
			var obj:GameObject = new GameObject();
			var meshRender:MeshRenderer = new MeshRenderer();
			obj.addComponent(meshRender);
			meshRender.geometry = new ResourceGeometry();
			
			meshRender.geometry.createFormVectors(lightParser.numVertices,lightParser.vertexData,lightParser.indexData,lightParser.uvData,lightParser.normalData,lightParser.tangentData);
			meshRender.material = new TextureMaterial(BitmapTexture.create(Stage3dUtils.bitmapData(AssetManage.getAsset(testLightDiffuseUrl)), true))
			
			meshRender.material.shader.addFilter(new DirectionalLightFilter(light));
			
			//法线贴图需要切线
			//meshRender.material.shader.addFilter(new NormalMapFilter(BitmapTexture.create(Stage3dUtils.bitmapData(AssetManage.getAsset(testLightNormalUrl)), true)));
			
			obj.transform.setPosition(0,7, -5);
			obj.transform.setRotation(0,180,0);
			view.scene.addChild(obj);
		}
		
		
		//操作相机
		private function onWheel(e:MouseEvent):void{
			view.camera.back(-e.delta);
		}
		
		private var start:Boolean;
		private var mousex:Number;
		private var mousey:Number;
		private function onDown(e:MouseEvent):void{
			start = true;
			mousex = sprite.stage.mouseX;
			mousey = sprite.stage.mouseY;
		}
		
		private function onUp(e:MouseEvent):void{
			start = false;
		}
		
		private var _ang:Number = 0;
		private function onMove(e:MouseEvent):void{
			if(start){
				var dx:Number = (sprite.stage.mouseX - mousex)*0.2;
				var dy:Number = (sprite.stage.mouseY - mousey)*0.2;
				view.camera.move(dx,dy);
			}
		}
		
		
		private function onEnter(e:Event):void{
			if(view)view.camera.move(2,1);
		}
		
		
	}
}